package controllers;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Random;


import javax.swing.JOptionPane;

import GUI.MainGUI;
import GUI.studentGUI.StudentExam;
import GUI.studentGUI.StudentExamReport;
import GUI.studentGUI.StudentExamined;
import GUI.studentGUI.StudentWindow;
import MsgPackage.AddComputerizedExamPack;
import MsgPackage.GetExaminedPack;
import MsgPackage.GetExamsPerStudentPack;
import MsgPackage.GetExtentionForExamPack;
import MsgPackage.StudentGetFilePack;
import MsgPackage.StudentUploadFilePack;
import client.ChatClient;

import common.Perror;

import entities.Answer;
import entities.ComputerizedExam;
import entities.ExtractedExam;
import entities.Question;
import entities.QuestionPerExam;
import entities.Student;
import files.Browse;
import files.MyFile;
import files.Save;

public class StudentController {

	private StudentWindow studentGUI;
	private StudentExamined studentExamendGUI;
	private StudentExam studentExamGUI;
	private StudentExamReport studentReportsGUI;

	private ChatClient client;
	private MainGUI mainGUI;
	private Student stdnt = null;

	final public static int EXIT = 1;
	final public static int REPORT = 2;
	final public static int EXAM = 3;
	final public static int MAIN = 4;
	final public static int COMPUTERIZED_EXAM = 5;
	final public static int MANUAL_EXAM = 6;
	final public static int COMBO_EXAMS = 7;
	public static final int DOWNLOAD_MANUAL_EXAM = 9;

	public StudentController(ChatClient client, MainGUI mainframe) {
		this.client = client;
		this.mainGUI = mainframe;
		mainGUI.setSize(MainGUI.setX, MainGUI.setY);
		studentGUI = new StudentWindow(this);
		mainGUI.setContentPane(studentGUI);
		if (stdnt == null) {
			stdnt = new Student();
			stdnt.setID(MainGUI.lgnUsr.getUserID());
		}
	}

	/**
	 * function: initAllQuestionPositions determines the order of the answers in
	 * each question of this exam. fills the 'rightAnswerPosition' array with
	 * the position of each right answer in the question.
	 */
	private ArrayList<Integer> initAllQuestionPositions(int size) {
		ArrayList<Integer> rightAnswerPosition = new ArrayList<Integer>();
		for (int i = 0; i < size; i++) {
			Integer temp = new Integer(randomizePositions());
			rightAnswerPosition.add(temp);
		}
		return rightAnswerPosition;
	}

	/**
	 * function: randomizePositions this function returns a random position ( a
	 * number between 0 and 3) for the right answer
	 */
	private int randomizePositions() {
		Random randomGenerator = new Random();
		int randomInt = randomGenerator.nextInt(4);
		return randomInt;
	}

	/*
	 * **************************************************************
	 * 						HANDLERS 							* 
	 * **************************************************************
	 */
	public void handleStudentGUI(int operation) {
		switch (operation) {
		case EXIT:// logout

			mainGUI.returnToLogin();
			break;

		case REPORT:// report
			if (studentReportsGUI == null)
				studentReportsGUI = new StudentExamReport(this);
			mainGUI.setContentPane(studentReportsGUI);
			getStudentReport();

			break;

		case EXAM:// pre-exam GUI

			if (studentExamGUI == null)
				studentExamGUI = new StudentExam(this);

			mainGUI.setContentPane(studentExamGUI);

			break;

		case MAIN:// main menu
			if (studentGUI == null)
				studentGUI = new StudentWindow(this);
			mainGUI.setContentPane(studentGUI);
			break;
		}
	}
	
	
/**	this function gets the exam code and the student ID, verifies that the
 * input is legal, gets the appropriate extracted exam (with it's questions)
 * and starts the get examined GUI.
 */
	public void startComputerizedExam(String examCode, String studentID) {
		GetExaminedPack gtExmnd;
		ArrayList<Integer> rightAnswerPosition;
		ArrayList<QuestionPerExam> qstns;
	
		//check the input phase:
		try {
		if (!(Integer.parseInt(studentExamGUI.getStudentID()) == stdnt.getID())) {
			Perror.pError("Please enter your ID correctly!");
			return;
		}
		}
		catch(NumberFormatException e)
		{
			Perror.pError("Please enter your ID correctly!");
			return;
		}
		
		// get the extracted exam and all components from the DB
		gtExmnd = new GetExaminedPack(stdnt, examCode);
		client.handleMessageFromClientUI(gtExmnd); // get the exam itself from DB

		gtExmnd = (GetExaminedPack) client.getMessage();
		
		//now check if the exam code is valid and the exam exists:
		if (gtExmnd.getExtractedExam().getExamCode()
				.equals(ExtractedExam.ERROR)) {
			Perror.pError("Exam Code is invalid, please check with your lecturer!");
			return;
		}
		//and check if the exam was already taken by this student:
		if (gtExmnd.getExtractedExam().getExamCode()
				.equals(ExtractedExam.ERROR_EXAM_ALREADY_TOOK_PLACE)) {
			Perror.pError("Dear student, you already took this exam.");
			return;
		}
		//then check if the exam is locked:
		if ((gtExmnd.getExtractedExam().getLockedExam())== 1)
		{
			Perror.pError("Exam is Locked. Please contact the lecturer.");
			return;
		}

		if ((gtExmnd.getExtractedExam().getExamExtractDate().getTime() + gtExmnd.getExtractedExam().getExamDurationTime().getTime() + gtExmnd.getExtractedExam().getExamExtantionDuration().getTime()) < Calendar.getInstance().getTimeInMillis())
		{
			Perror.pError("Exam is already took place and it's time is up. Please contact the lecturer.");
			return;
		}

		
		//finally! we can start initiating the getting examined:
		rightAnswerPosition = initAllQuestionPositions(gtExmnd.getQuestions()
				.size()); // initialize the answers' position in all question

		qstns = new ArrayList<QuestionPerExam>();
		qstns.addAll(gtExmnd.getQuestions());

		if (studentExamendGUI == null) {					//init the examination GUI
			studentExamendGUI = new StudentExamined(this,
					gtExmnd.getExtractedExam(), qstns, rightAnswerPosition);
			mainGUI.setContentPane(studentExamendGUI);		//and start the exam.
			if(gtExmnd.getExtractedExam().getExamExtantionDuration().getTime()==0)
				new ExtantionForExam(gtExmnd.getExtractedExam()).start();
			
		}
	}
	
	private class ExtantionForExam extends Thread {
		private ExtractedExam extExam;
		public ExtantionForExam(ExtractedExam exm) {
			extExam = exm;
		}

		public void run() {
			GetExtentionForExamPack examExtentionPck = new GetExtentionForExamPack(extExam);
			client.handleMessageFromClientUI(examExtentionPck);
			examExtentionPck = (GetExtentionForExamPack) client.getMessage();
			if ((examExtentionPck.isApproved()) && (examExtentionPck.getExtrctExam().getExamCode().equals(extExam.getExamCode())))
				studentExamendGUI.extandTimeDuration(examExtentionPck.getExtrctExam().getExamExtantionDuration().getTime());
			JOptionPane.showMessageDialog(mainGUI, "Please notice, you have got extention for the exam.");

		}
	}
	
	/**this function gets a computerizedExam filled with the exam that the 
	 * student has just finished taking and most of it's components. the 
	 * function takes
	 * 
	 * @param cptExm
	 */
	public void finishExam(ComputerizedExam cptExm) {
	
		AddComputerizedExamPack cmpExmPck = new AddComputerizedExamPack();
		cptExm.setStudentID(Integer.parseInt(studentExamGUI.getStudentID()));
		cptExm.setExamGrade(checkExam(cptExm.getAnswers()));
		cptExm.setExamApproved(false);
		
		cmpExmPck.SetComputerizedExam(cptExm);
		cmpExmPck.getStdnt().setID(stdnt.getID());
		client.handleMessageFromClientUI(cmpExmPck);	//now send to the server
		cmpExmPck = (AddComputerizedExamPack)client.getMessage();
		
		//now check if there was an error with saving the exam to DB:
		if (cmpExmPck.getComputerizedExam().getExamCode().equals(ComputerizedExam.Error))
			Perror.pError("Exam couldn't be saved, please advise your lacturer!");
		ArrayList<Answer> answers = cmpExmPck.getComputerizedExam().getAnswers();
		for (int i = 0; i < answers.size(); i++)
			if (answers.get(i).getQuestionID() == Question.ERROR)
			{
				Perror.pError("Exam couldn't be saved, please advise your lacturer!");
				break;
			}
		studentExamGUI.clearAll();
		handleStudentGUI(MAIN);
		
	}
	/**
	 * this function checks the exam that the student has just finished 
	 * @param answers
	 * @return the exam score
	 */
	private int checkExam(ArrayList<Answer> answers)
	{
		int score = 0;
		ArrayList<QuestionPerExam> qstns = studentExamendGUI.getQuestions();
		
		for (int i=0; i< answers.size(); i++)		//go over all questions that were answered
		{
			if(answers.get(i).getSelectedAnswer() == 1) 	//and if the correct answer was chosen
				score = (score + (qstns.get(i).getQuestionGrade()));		//add it's worth ot score to the total score.
		}
		return score;
	}
	
	
	private void getStudentReport() {
		GetExamsPerStudentPack exmPerStdnt = new GetExamsPerStudentPack(stdnt);
		client.handleMessageFromClientUI(exmPerStdnt);
		exmPerStdnt = (GetExamsPerStudentPack) client.getMessage();
		studentReportsGUI.addExams(exmPerStdnt.getComputerizedExams());
		studentReportsGUI.addQsForExams(exmPerStdnt.getAllQsforExams());
	}

	
	
	public void getFile(String examCode) {
		StudentGetFilePack examFile = new StudentGetFilePack(examCode);
		client.handleMessageFromClientUI(examFile);

		examFile = (StudentGetFilePack) client.getMessage();
		if (examFile.getGood()) {
			studentExamGUI.lock(false);
			Save save = new Save(examFile.getMyfile());
			JOptionPane.showMessageDialog(mainGUI, "GOOD LUCK");
		} else
			JOptionPane.showMessageDialog(mainGUI, "Incorrect exam code");

	}

	public void upLoad(String examCode, int SID) {
		Browse b = new Browse();
		MyFile file = b.getFile();
		StudentUploadFilePack examFile = new StudentUploadFilePack(examCode,
				SID);
		System.out.print(file.getName());
		examFile.setMyfile(file);
		client.handleMessageFromClientUI(examFile);
		examFile = (StudentUploadFilePack) client.getMessage();
		if (examFile.getSuccess()) {
			JOptionPane.showMessageDialog(mainGUI, "File upload successfully");
		} else
			JOptionPane.showMessageDialog(mainGUI, "file upload failed");
	}

	public void examTimeOver(String string) {
		JOptionPane.showMessageDialog(mainGUI, string);
		
	}

}
